/*
ont-space - The ontology-based resource metadata repository
Copyright (c) 2006-2008, Information Eng. Research Unit - Univ. of Alcalá
http://www.cc.uah.es/ie
This library is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free
Software Foundation; either version 2.1 of the License, or (at your option)
any later version.
This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details.
You should have received a copy of the GNU Lesser General Public License along
with this library; if not, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */
package org.ontspace.comp.owl;

import com.hp.hpl.jena.ontology.Individual;
import com.hp.hpl.jena.ontology.ObjectProperty;
import com.hp.hpl.jena.ontology.OntClass;
import com.hp.hpl.jena.ontology.OntModel;
import com.hp.hpl.jena.ontology.Ontology;
import com.hp.hpl.jena.ontology.Ontology.*;
import com.hp.hpl.jena.rdf.model.NodeIterator;
import com.hp.hpl.jena.rdf.model.Property;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.rdf.model.Statement;
import com.hp.hpl.jena.rdf.model.StmtIterator;
import com.hp.hpl.jena.util.iterator.ExtendedIterator;
import java.net.URISyntaxException;
import java.net.URI;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.ontspace.MetadataRecordReference;
import org.ontspace.owl.MetadataRepositoryImpl;
import org.ontspace.owl.QueryManagerImpl;
import org.ontspace.comp.COMPQueryManager;
import org.ontspace.owl.MetadataRecordReferenceImpl;

/**
 * Implementation for a competency query manager
 */
public class COMPQueryManagerImpl extends QueryManagerImpl
        implements COMPQueryManager {

    private static MetadataRepositoryImpl _rep;
    private static List<Ontology> _onts =
            new ArrayList<Ontology>();
    private List<URI> _uriList;
    private String _nsName =
            "http://www.cc.uah.es/ie/ont/cLom-ospace";
    private String _nsNameLom =
            "http://www.cc.uah.es/ie/ont/lom-ospace";
    private String _nsNameGCS =
            "http://www.cc.uah.es/ie/ont/gcs-ospace";
    private OntModel _OntModel;

    /** 
     * Creates a new instance of COMPQueryManagerImpl
     */
    public COMPQueryManagerImpl(MetadataRepositoryImpl rep, HashMap params)
            throws ClassNotFoundException, NoSuchMethodException {
        super(rep);
        _rep =
                rep;
        this._uriList =
                new ArrayList<URI>();
        addRequiredOntologies(params);

    }

    /**
     * Adds the required ontology to the ontologies' list
     * @param ont Ontology to be added into the list
     */
    @Override
    public void addOntologyRef(Ontology ont) {
        if (ont != null) {
            _onts.add(ont);
        }
    }

    /**
     * Adds the required ontologies URI to the object
     * @param params uri params
     */
    private void addRequiredOntologies(HashMap params) {
        String ontologyUri;
        int i =
                1;
        boolean finished =
                false;
        while (!finished) {
            String paramName =
                    "uri" + i++;
            ontologyUri =
                    (String) params.get(paramName);
            if (ontologyUri != null) {
                try {
                    this._uriList.add(new URI(ontologyUri));
                } catch (URISyntaxException ex) {
                    Logger.getLogger(QueryManagerImpl.class.getName()).
                            log(Level.SEVERE, null, ex);
                }
            } else {
                finished =
                        true;
            }
        }
    }

    /**
     * Gets a list with the URIs of the ontologies required by the query manager
     * @return A list whith the USIs of the required ontologies
     */
    @Override
    public List<URI> getRequiredOntologies() {
        return this._uriList;
    }

    /**
     * Gets the ontModel asociated at competency queryManager
     * @return the ontModel
     */
    public OntModel getOntologyModel() {
        OntModel ontmodel =
                null;

        for (int i =
                0; i < _onts.size(); i++) {
            Ontology ont =
                    _onts.get(i);

            System.out.println(ont.getNameSpace() + ont.getLocalName());
            String ns =
                    ont.getNameSpace() + ont.getLocalName();
            if (ns.compareTo(_nsName) == 0) {
                ontmodel =
                        ont.getOntModel();

            }
        }
        return ontmodel;
    }

    /**
     *  Launches a query for  a particular element in the ontology    
     * @param competList the list to competencies to search
     * @return COMPQueryResultImpl object that have the Set of 
     * MetadataRecordReference
     */
    public COMPQueryResultImpl searchByCompetency(List<String> competList) {
        if (_OntModel == null) {
            this._OntModel =
                    this.getOntologyModel();
        }
        COMPQueryResultImpl queryResult =
                new COMPQueryResultImpl();
        Set<MetadataRecordReference> instancesR =
                new HashSet<MetadataRecordReference>();

        OntClass cLO =
                _OntModel.getOntClass(_nsName + "#cLomLearningObject");
        ExtendedIterator cLomInstances =
                cLO.listInstances();

        while (cLomInstances.hasNext()) {

            Individual cLomInstance =
                    (Individual) cLomInstances.next();
            String loId =
                    _nsNameLom + "#" + cLomInstance.getLocalName().toString();
            ObjectProperty propSCC =
                    _OntModel.getObjectProperty(_nsName +
                    "#SemanticCompetencyClassificationLO");
            NodeIterator sccInstances =
                    cLomInstance.listPropertyValues(propSCC);
            while (sccInstances.hasNext()) {
                Resource sccInstance =
                        (Resource) sccInstances.next();

                Property propSCD =
                        _OntModel.getProperty(_nsName +
                        "#semanticCompetencyDefinition");
                StmtIterator scdInstances =
                        sccInstance.listProperties(propSCD);
                while (scdInstances.hasNext()) {
                    Statement scdInstance =
                            scdInstances.nextStatement();
                    String id =
                            scdInstance.getObject().toString();
                    Iterator it =
                            competList.iterator();
                    while (it.hasNext()) {
                        String compId =
                                (String) it.next();
                        if (compId.compareTo(id) == 0) {
                            boolean encontrado =
                                    false;
                            MetadataRecordReference mrr =
                                    new MetadataRecordReferenceImpl
                                      (_rep.getRepositoryURI(),loId);
                            for (Iterator itQR =
                                    queryResult.getMetadataRecordReference().
                                    iterator();
                                    itQR.hasNext();) {
                                while (itQR.hasNext()) {
                                    MetadataRecordReference mrrit =
                                            (MetadataRecordReference) itQR.next();
                                    String idmrr =
                                            mrrit.getLocalMetadataRecordId();
                                    if (idmrr == loId) {
                                        encontrado =
                                                true;
                                    }
                                }
                            }
                            if (!encontrado) {
                                {
                                    queryResult.getMetadataRecordReference().add(mrr);
                                    System.out.println("Añadiendo el id: " +
                                            loId);
                                    encontrado =
                                            false;
                                }
                            }
                        }
                    }
                }

            }
        }
        return queryResult;

    }

    /**
     * Obtains the competencies required by one learning object
     * @param loIdentifier the learning object identifier
     * @return required competencies list
     */
    public List<String> getRequiredCompetencies(String loIdentifier) {
        if (_OntModel == null) {
            this._OntModel =
                    this.getOntologyModel();
        }

        List<String> results =
                new ArrayList();


        Individual cLomInstance =
                _OntModel.getIndividual(loIdentifier);
        ObjectProperty propSCC =
                _OntModel.getObjectProperty(_nsName +
                "#SemanticCompetencyClassificationLO");
        NodeIterator sccInstances =
                cLomInstance.listPropertyValues(propSCC);

        while (sccInstances.hasNext()) {
            Resource sccInstance =
                    (Resource) sccInstances.next();

            Property propSCD =
                    _OntModel.getProperty(_nsName +
                    "#semanticCompetencyDefinition");
            StmtIterator scdInstances =
                    sccInstance.listProperties(propSCD);
            while (scdInstances.hasNext()) {
                Statement scdInstance =
                        scdInstances.nextStatement();
                String id =
                        scdInstance.getObject().toString();
                results.add(id);

            }

        }

        return results;

    }
}

